﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using COFE.Core.Lister;
using COFE.Core;
using COFE.Web;
using COFE.Core.Validater;

namespace COFE.IO.COFEWS
{
    public class COFEWSPropertyProvider : PropertyProviderBase<Entry>
    {
        #region Constructor
        public COFEWSPropertyProvider(COFEWSDirectoryLister lister, Entry entry)
            : base(entry)
        {            
            registerProperties(lister.ListerKey, entry.BaseType == EntryBaseType.File);
        }
        #endregion

        #region Methods

        public override void Refresh()
        {
            base.Refresh();
            var selfLink = EmbeddedEntry.GetLinks().First(
                l => l.Relation == RelationType.Self).Uri;
            EmbeddedEntry = _lister.getEntry(selfLink);
        }

        private void registerProperties(string listerKey, bool isFile)
        {

            #region Register COFEWSProperties

            Func<Entry, RelationType, Link> findLink = (e, rel) =>
                {
                    return e.GetLinks().FirstOrDefault(l => l.Relation == rel);
                };

            Action<RelationType, COFEWSProperties> registerLink = (rel, prop) =>
                {
                    if (findLink(EmbeddedEntry, rel) != null)
                        base.RegisterMethod(prop,
                            (e, p) =>
                            {
                                return findLink(e, rel).Uri;
                            });
                };

            registerLink(RelationType.Self, COFEWSProperties.EntryUri);
            registerLink(RelationType.Metadata, COFEWSProperties.MetadataUri);
            registerLink(RelationType.Download, COFEWSProperties.StreamUri);
            registerLink(RelationType.Upload, COFEWSProperties.StreamUri);
            registerLink(RelationType.Stream, COFEWSProperties.StreamUri);
            registerLink(RelationType.List, COFEWSProperties.ListUri);
            RegisterMethod(COFEWSProperties.EntryPath, (e, p) => e.Path);

            #endregion

            Func<Entry, object, PropertyPair> lookupFromMetadata = (e, p) =>
                {
                    foreach (var data in e.Metadata)
                        if (data.Property.Equals(p))
                            return data;
                    if (PropertyTypeExtension.HasDefaultValue(p))
                        return
                            new PropertyPair(p,
                            PropertyTypeExtension.GetDefaultValue(p));
                    return null;
                };

            base.RegisterMethod(FileSystemInfoProperties.FullParseName, (e, p) =>
            {
                string path = COFEWSPath.ToCOFEPath(e.Path);
                return COFEPath.FormatFullParseName(listerKey, path);
            });
            base.RegisterMethod(FileSystemInfoProperties.ParentParseName, (e, p) =>
            {
                string parentPath = COFEPath.GetDirectoryName(
                    this.GetProperty(FileSystemInfoProperties.FullParseName)
                    .ValueAsString);
                return (string.IsNullOrEmpty(parentPath)) ? null : parentPath;
            });

            base.RegisterMethod(FileSystemInfoProperties.Name, (e, p) => e.Name );
            base.RegisterMethod(FileSystemInfoProperties.Label, (e, p) => e.Name );

            base.RegisterMethod(FileSystemInfoProperties.IsExists, (e, p) => { return e != null; });
            base.RegisterMethod(FileSystemInfoProperties.IsFileSystem, (e, p) => { return false; });

            base.RegisterMethod(FileSystemInfoProperties.FileAttributes,
                (e, p) =>
                {
                    var retVal = COFE.Core.FileAttributes.ReadOnly;
                    if (!isFile)
                        retVal |= COFE.Core.FileAttributes.Directory;
                    return retVal;
                });

            base.RegisterMethod(FileSystemInfoProperties.COFEAttributes, (e, p) =>
            {
                return !isFile ? COFEAttributes.Browsable :
                    COFEAttributes.None;
            });

            base.RegisterMethod(FileSystemInfoProperties.CreationTimeUtc,
                (e, p) => { return this.GetProperty(FileSystemInfoProperties.LastWriteTimeUtc).ValueAsUtcDateTime; });
            base.RegisterMethod(FileSystemInfoProperties.LastAccessTimeUtc,
                (e, p) => { return this.GetProperty(FileSystemInfoProperties.LastWriteTimeUtc).ValueAsUtcDateTime; });
            base.RegisterMethod(FileSystemInfoProperties.LastWriteTimeUtc,
                (e, p) =>
                {
                    return e.UtcTime;                        
                        //lookupFromMetadata(e, FileSystemInfoProperties
                        //.LastWriteTimeUtc).ValueAsUtcDateTime;
                });

            if (isFile)
            {
                base.RegisterMethod(FileInfoProperties.Length,
                    (e, p) =>
                    {
                        return e.Length;   
                        //return lookupFromMetadata(e, FileInfoProperties.Length)
                        //.ValueAsInt64;
                    });
            }
            else
            {

                base.RegisterMethod(DirectoryInfoProperties.DirectoryType,
                    (e, p) =>
                    {
                        if (e.Path == "") return DirectoryTypeEnum.dtVolume;
                        else return DirectoryTypeEnum.dtFolder;
                    }
                    );

                base.RegisterMethod(DirectoryInfoProperties.IsFileBasedFS, (e, p) => { return false; });
            }

        }

        #endregion

        #region Data

        COFEWSDirectoryLister _lister;

        #endregion

        #region Public Properties


        #endregion
    }
}
